En este laboratorio usaremos información del Libro de Ordenes de Criptomonedas de diversos exchanges internacionales, con el objetivo primario de visualizar y modelar la microestructura del mercado por medio del comportamiento de Libro de Ordenes y sus caracteristicas como; Matching Engine, Levels, Ask-Bid Volumnes, etc.
Utilizando la libreria ccxt de python para consultar información del Libro de Ordenes (LO) de criptomonedas de diversos exchanges, extraer; ask, ask-volume, bid, bid-volume y spread; construir las series de tiempo:
Graficar usando plotly para python cada una de ellas y para cada uno de los exchanges.
import data
import pandas as pd
import functions
import plotly.express as px
import visualizations
import numpy as np
In order to run this notebook, it is necessary to have installed and/or have the requirements.txt file with the following:
The following are the file dependencies that are needed to run this notebook:
%%capture
# Install all the pip packages in the requirements.txt
import sys
!{sys.executable} -m pip install -r requirements.txt
Para descargar la información sobre las cryptos utilizamos la API de CCXT. Descargamos los trading books de las siguientes plataformas: kucoin, bittrex, y bitfinex. Utilizamos dos monedas: BTCUSDT y ETHEUR. Para cada una de las monedas tenemos las ordenes de compra y venta de las plataformas mencionadas anteriormente. La información fue descargada durante una hora. Puede ser que tengamos algunos brincos en la data ya que la API tenía fallas por lo que durante la hora que estuvo descargando, la conexión falló.
#df1 = pd.read_json('files\orderbooks_26abr2023_BTCUSDT.json')
df1 = pd.read_json('files\orderbooks_27abr2023_BTCUSDT.json')
df1.head()
#df2 = pd.read_json('files\orderbooks_26abr2023_ETHEUR.json')
df2 = pd.read_json('files\orderbooks_27abr2023_ETHEUR.json')
df2.head()
df1 = functions.vwap(df1)
df2 = functions.vwap(df2)
df = pd.concat([df1, df2])
df[['Symbol','exchange', 'datetime', 'level', 'ask_volume', 'bid_volume', 'total_volume', 'mid_price', 'VWAP']]
La funcion de VWAP saca el Volume Weighted Average Price (VWAP). Es una métrica finacniera utilizada por traders para calcular el precio promedio de un activo sobre cierto periodo de tiempo. Toma en cuenta tanto el precio como el volumen de trades.
Levels Bid volume Ask volume Total volume Mid price VWAP
fig = px.line(df[df['Symbol'] == list(set(df['Symbol']))[0]], x="datetime", y="level", color='exchange', title=list(set(df['Symbol']))[0]+" level over period")
fig.show()
fig = px.line(df[df['Symbol'] == list(set(df['Symbol']))[0]], x="datetime", y="bid_volume", color='exchange', title=list(set(df['Symbol']))[0]+" bid volume over period")
fig.show()
fig = px.line(df[df['Symbol'] == list(set(df['Symbol']))[0]], x="datetime", y="ask_volume", color='exchange', title=list(set(df['Symbol']))[0]+" ask volume over period")
fig.show()
fig = px.line(df[df['Symbol'] == list(set(df['Symbol']))[0]], x="datetime", y="total_volume", color='exchange', title=list(set(df['Symbol']))[0]+" total volume over period")
fig.show()
fig = px.line(df[df['Symbol'] == list(set(df['Symbol']))[0]], x="datetime", y="mid_price", color='exchange', title=list(set(df['Symbol']))[0]+" mid prices over period")
fig.show()
fig = px.line(df[df['Symbol'] == list(set(df['Symbol']))[0]], x="datetime", y="VWAP", color='exchange', title=list(set(df['Symbol']))[0]+" VWAP over period")
fig.show()
Como podemos observar, en algunas de las gráficas podemos ver una volatilidad bastante representativa, a su vez donde hay más movimiento es en kucoin, en cuanto a los mid prices no hay tanta diferencia.
fig = px.line(df[df['Symbol'] == list(set(df['Symbol']))[1]], x="datetime", y="level", color='exchange', title=list(set(df['Symbol']))[1]+" level over period")
fig.show()
fig = px.line(df[df['Symbol'] == list(set(df['Symbol']))[1]], x="datetime", y="bid_volume", color='exchange', title=list(set(df['Symbol']))[1]+" bid volume over period")
fig.show()
fig = px.line(df[df['Symbol'] == list(set(df['Symbol']))[1]], x="datetime", y="ask_volume", color='exchange', title=list(set(df['Symbol']))[1]+" ask volume over period")
fig.show()
fig = px.line(df[df['Symbol'] == list(set(df['Symbol']))[1]], x="datetime", y="total_volume", color='exchange', title=list(set(df['Symbol']))[1]+" total volume over period")
fig.show()
fig = px.line(df[df['Symbol'] == list(set(df['Symbol']))[1]], x="datetime", y="mid_price", color='exchange', title=list(set(df['Symbol']))[1]+" mid prices over period")
fig.show()
fig = px.line(df[df['Symbol'] == list(set(df['Symbol']))[1]], x="datetime", y="VWAP", color='exchange', title=list(set(df['Symbol']))[1]+" VWAP over period")
fig.show()
Contrario al caso anterior, hay mayor diferencia en VWAP y mayor movimiento en otras plataformas, también mucha diferencia en los mid prices.
df_rolls1 = functions.rolls(df1, 30)
df_rolls2 = functions.rolls(df2, 30)
Rolls's Effective Spread es una medida del valor real del costo de transaccion de un activo. Toma en cuenta tanto los costos explicitos como los implicitos. Richar Roll propuse esta medida en 1984, por lo que lleva su nombre. Nosotros utilizamos un lag de 30 minutos porque nuestros closing prices los teníamos por minuto, y asi teníamos un Effective Spread más visible. En la función se puede ajustar al Lag que uno quiera.
df_rolls1[0][['close_price', 'spread', 'Rolls Spread']]
df_rolls1[1][['close_price', 'spread', 'Rolls Spread']]
df_rolls1[2][['close_price', 'spread', 'Rolls Spread']]
df_rolls2[0][['close_price', 'spread', 'Rolls Spread']]
df_rolls2[1][['close_price', 'spread', 'Rolls Spread']]
df_rolls2[2][['close_price', 'spread', 'Rolls Spread']]
Como es evidente, en algumas plataformas hay más volatilidad que en otras, esto se puede deber a varios factores ajenos a la criptomoneda, desde el horario en que se descargó la información hasta las comisiones que tiene cada una. En este laboratorio no sólo se nos enseñó a analizar desde otra perspectiva a las criptos sino a utilizar herramientas que nunca habíamos utilizado, el hecho de que usemos plotly le da un valor agregado a cualquier trabajo que entreguemos. Uno de los inconvenientes que tuvimos fue la descarga de datos, era muy inestable, afortunadamente se solucionó por medio de código.